วศ
วศิน อนันต์
QC LEAD

📜 ประวัติการใช้งาน (Audit Log)

บันทึกทุกกิจกรรมในระบบตามมาตรฐาน · 136 events · 15 modules · 5 severity levels · Immutable INSERT-only

ℹ️
INFO (ทั่วไป)
0
view · list · search
📝
AUDIT (CRUD)
0
create · update · delete
🔐
SECURITY
0
auth · RBAC · permission
⚠️
WARNING
0
anomaly detected
🚨
CRITICAL
0
override · force-close
เวลา ระดับ Event ID ผู้กระทำ ข้อความ IP
Event ID Module Entity Action Severity ข้อความ Diff Retention

📐 หลักการบันทึก Audit Trail · 10 ข้อ

ทุก event ที่ระบบบันทึก ต้องเป็นไปตามหลักการเหล่านี้ — Source of Truth ในการออกแบบทุก API endpoint

ระดับความรุนแรง (Severity) · 5 ระดับ

กำหนดความสำคัญและ retention · SECURITY/CRITICAL trigger alert

ระดับการใช้งานAlertเก็บนาน

นโยบาย Retention

ระยะเวลาเก็บรักษา log ตามประเภท + กฎหมาย PDPA

🔬 Field Tracking · ฟิลด์ที่เก็บ before/after diff

เฉพาะฟิลด์ที่อยู่ในรายการนี้เท่านั้นที่จะถูกบันทึก diff ลงใน changes JSONB · ฟิลด์ PII (password, OTP, credit card) ถูกแยกออกเสมอ

🔌 API Endpoint สำหรับบันทึก Audit Log

ทุกหน้าจอเรียก endpoint นี้หลัง action ที่ต้อง audit — fire-and-forget แบบ async · server validate + persist + (option) trigger alert

POST /api/audit-logs
// Request body { "event_id": "PRJ-006", "entity_type": "project", "entity_id": "550e8400-e29b-41d4-a716-446655440000", "action": "project.close", "changes": { "status": { "from": "active", "to": "closed" }, "closed_at": { "from": null, "to": "2026-06-01T14:30:00Z" } }, "reason": "งานเสร็จสมบูรณ์ ตรวจรับงานครบทุก checklist" // required for CRITICAL severity } // Response 201 Created { "id": 12345678, "occurred_at": "2026-06-01T14:30:01.234Z", "severity": "AUDIT", "message_th": "สมชาย ปิดโครงการ 'อาคารสำนักงาน 25 ชั้น' เรียบร้อย", "message_en": "Somchai closed project 'Office Tower 25F'" }

🗄️ PostgreSQL Schema · ตาราง audit_logs

ทุก audit event = 1 row ใน audit_logs · INSERT-only · trigger บล็อก UPDATE/DELETE

ColumnTypeRequiredNotes
idBIGSERIALPK auto
org_idUUIDTenant scope · FK organizations
user_idUUIDoptionalActor · NULL สำหรับ system events
event_idVARCHAR(20)เช่น AUTH-001, PRJ-007
severityVARCHAR(20)INFO / AUDIT / SECURITY / WARNING / CRITICAL
entity_typeVARCHAR(40)เช่น 'project', 'task', 'ncr'
entity_idUUID✓** ยกเว้น system events
actionVARCHAR(60)เช่น 'project.close'
message_thTEXTRender จาก template ตอน insert
message_enTEXTRender จาก template
changesJSONBupdate onlybefore/after diff · ห้ามเก็บ PII
reasonTEXTCRITICAL onlyUser-provided reason
ip_addressINETใช้ x-forwarded-for ถ้าผ่าน proxy
user_agentTEXTtruncate 500 chars
session_idUUID✓** ยกเว้น system
occurred_atTIMESTAMPTZUTC · DEFAULT NOW()

📦 SDK Helper · auditLog() — ใช้ทุกที่

Helper ที่ wrap API endpoint · จัดการ session, IP, user-agent ให้อัตโนมัติ · auto-render TH/EN message

// frontend/src/lib/auditLog.ts export async function auditLog(opts: { eventId: string, // "PRJ-006" — must match Event Catalog entityType: string, entityId?: string, changes?: Record<string, { from: unknown; to: unknown }>, reason?: string // required for CRITICAL events }) { const resp = await fetch('/api/audit-logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(opts) }); if (!resp.ok) throw new Error('Audit log failed'); return resp.json(); } // Usage in any page (after a state-changing action) await closeProjectApi(projectId, { reason }); await auditLog({ eventId: 'PRJ-006', entityType: 'project', entityId: projectId, changes: { status: { from: 'active', to: 'closed' } } });

🛡️ Security & Compliance Rules

  • Immutable: trigger PostgreSQL block ทุก UPDATE/DELETE บน audit_logs · ใช้ partition by month เพื่อ archive
  • PII redaction: middleware strip ฟิลด์ password, password_hash, otp, credit_card, tax_id จาก changes ก่อน insert
  • Reason required: ถ้า severity = CRITICAL แต่ reason ว่างเปล่า → 422 Unprocessable
  • Alert pipeline: SECURITY ≥ 5/5min → email admin · CRITICAL → SMS + email admin + owner ทันที
  • Index: (org_id, occurred_at DESC), (entity_type, entity_id), (user_id, occurred_at DESC)
  • Visibility: User เห็นของตน · QCM/PM เห็น project ที่ตน manage · Admin เห็นทุก log ของ org · Compliance officer ข้าม tenant ได้
บันทึก ✓